home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.3 Development Libraries / SGI IRIX 6.3 Development Libraries.iso / dist6.3 / gl_dev.idb / usr / share / src / OpenGL / toolkits / libaux / shapes.c.z / shapes.c
Encoding:
C/C++ Source or Header  |  1996-12-06  |  27.0 KB  |  1,057 lines

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <GL/gl.h>
  4. #include <GL/glu.h>
  5. #include "aux.h"
  6. #include "3d.h"
  7.  
  8. #if defined(__cplusplus) || defined(c_plusplus)
  9. #define class c_class
  10. #endif
  11.  
  12. #define SPHEREWIRE    0
  13. #define CUBEWIRE    1
  14. #define BOXWIRE        2
  15. #define TORUSWIRE    3
  16. #define CYLINDERWIRE    4
  17. #define ICOSAWIRE    5
  18. #define OCTAWIRE    6
  19. #define TETRAWIRE    7
  20. #define DODECAWIRE    8
  21. #define CONEWIRE    9
  22. #define SPHERESOLID    10
  23. #define CUBESOLID    11
  24. #define BOXSOLID    12
  25. #define TORUSSOLID    13
  26. #define CYLINDERSOLID    14
  27. #define ICOSASOLID    15
  28. #define OCTASOLID    16
  29. #define TETRASOLID    17
  30. #define DODECASOLID    18
  31. #define CONESOLID    19
  32.  
  33. #define PI 3.1415926535897
  34.  
  35. /*    structure for each geometric object    */
  36. typedef struct model {
  37.     GLuint list;    /*  display list to render object   */
  38.     struct model *ptr;    /*  pointer to next object    */
  39.     int numParam;    /*  # of parameters        */
  40.     GLdouble *params;    /*  array with parameters    */
  41. } MODEL, *MODELPTR;
  42.  
  43. /*    array of linked lists--used to keep track of display lists 
  44.  *    for each different type of geometric object.
  45.  */
  46. static MODELPTR lists[25] = {
  47.     NULL, NULL, NULL, NULL, NULL,
  48.     NULL, NULL, NULL, NULL, NULL,
  49.     NULL, NULL, NULL, NULL, NULL,
  50.     NULL, NULL, NULL, NULL, NULL,
  51.     NULL, NULL, NULL, NULL, NULL
  52. };
  53.  
  54. GLuint findList (int index, GLdouble *paramArray, int size);
  55. int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size);
  56. GLuint makeModelPtr (int index, GLdouble *sizeArray, int count);
  57.  
  58. static void drawbox(GLdouble, GLdouble, GLdouble, 
  59.     GLdouble, GLdouble, GLdouble, GLenum);
  60. static void doughnut(GLdouble, GLdouble, GLint, GLint, GLenum);
  61. static void icosahedron(GLdouble *, GLdouble, GLenum);
  62. static void octahedron(GLdouble *, GLdouble, GLenum);
  63. static void tetrahedron(GLdouble *, GLdouble, GLenum);
  64. static void subdivide(int, GLdouble *, GLdouble *, GLdouble *,
  65.     GLdouble *, GLdouble, GLenum, int);
  66. static void drawtriangle(int, int, int,
  67.     GLdouble *, GLdouble, GLenum, int);
  68. static void recorditem(GLdouble *, GLdouble *, GLdouble *,
  69.     GLdouble *, GLdouble, GLenum, int);
  70. static void initdodec(void);
  71. static void dodecahedron(GLdouble *, GLdouble, GLenum);
  72. static void pentagon(int, int, int, int, int, GLenum);
  73.  
  74.  
  75. /*  Render wire frame or solid sphere.  If no display list with
  76.  *  the current model size exists, create a new display list.
  77.  */
  78. void auxWireSphere (GLdouble radius)
  79. {
  80.     GLUquadricObj *quadObj;
  81.     GLdouble *sizeArray;
  82.     GLuint displayList;
  83.  
  84.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  85.     *sizeArray = radius;
  86.     displayList = findList (SPHEREWIRE, sizeArray, 1);
  87.  
  88.     if (displayList == 0) {
  89.     glNewList(makeModelPtr (SPHEREWIRE, sizeArray, 1),
  90.         GL_COMPILE_AND_EXECUTE);
  91.         quadObj = gluNewQuadric ();
  92.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  93.         gluSphere (quadObj, radius, 16, 16);
  94.     glEndList();
  95.     }
  96.     else {
  97.     glCallList(displayList);
  98.     free (sizeArray);
  99.     }
  100. }
  101.  
  102. void auxSolidSphere (GLdouble radius)
  103. {
  104.     GLUquadricObj *quadObj;
  105.     GLdouble *sizeArray;
  106.     GLuint displayList;
  107.  
  108.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  109.     *sizeArray = radius;
  110.     displayList = findList (SPHERESOLID, sizeArray, 1);
  111.  
  112.     if (displayList == 0) {
  113.     glNewList(makeModelPtr (SPHERESOLID, sizeArray, 1),
  114.         GL_COMPILE_AND_EXECUTE);
  115.         quadObj = gluNewQuadric ();
  116.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  117.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  118.         gluSphere (quadObj, radius, 16, 16);
  119.     glEndList();
  120.     }
  121.     else {
  122.     glCallList(displayList);
  123.     free (sizeArray);
  124.     }
  125. }
  126.  
  127. /*  Render wire frame or solid cube.  If no display list with
  128.  *  the current model size exists, create a new display list.
  129.  */
  130. void auxWireCube (GLdouble size)
  131. {
  132.     GLdouble *sizeArray;
  133.     GLuint displayList;
  134.  
  135.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  136.     *sizeArray = size;
  137.     displayList = findList (CUBEWIRE, sizeArray, 1);
  138.  
  139.     if (displayList == 0) {
  140.     glNewList(makeModelPtr (CUBEWIRE, sizeArray, 1),
  141.         GL_COMPILE_AND_EXECUTE);
  142.         drawbox(-size/2., size/2., -size/2., size/2., 
  143.         -size/2., size/2., GL_LINE_LOOP);
  144.     glEndList();
  145.     }
  146.     else {
  147.     glCallList(displayList);
  148.     free (sizeArray);
  149.     }
  150. }
  151.  
  152. void auxSolidCube (GLdouble size)
  153. {
  154.     GLdouble *sizeArray;
  155.     GLuint displayList;
  156.  
  157.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  158.     *sizeArray = size;
  159.     displayList = findList (CUBESOLID, sizeArray, 1);
  160.  
  161.     if (displayList == 0) {
  162.     glNewList(makeModelPtr (CUBESOLID, sizeArray, 1),
  163.         GL_COMPILE_AND_EXECUTE);
  164.         drawbox(-size/2., size/2., -size/2., size/2., 
  165.         -size/2., size/2., GL_QUADS);
  166.     glEndList();
  167.     }
  168.     else {
  169.     glCallList(displayList);
  170.     free (sizeArray);
  171.     }
  172. }
  173.  
  174. /*  Render wire frame or solid cube.  If no display list with
  175.  *  the current model size exists, create a new display list.
  176.  */
  177. void auxWireBox (GLdouble width, GLdouble height, GLdouble depth)
  178. {
  179.     GLdouble *sizeArray, *tmp;
  180.     GLuint displayList;
  181.  
  182.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
  183.     tmp = sizeArray;
  184.     *tmp++ = width;
  185.     *tmp++ = height;
  186.     *tmp++ = depth;
  187.     displayList = findList (BOXWIRE, sizeArray, 3);
  188.  
  189.     if (displayList == 0) {
  190.     glNewList(makeModelPtr (BOXWIRE, sizeArray, 3),
  191.         GL_COMPILE_AND_EXECUTE);
  192.         drawbox(-width/2., width/2., -height/2., height/2., 
  193.         -depth/2., depth/2., GL_LINE_LOOP);
  194.     glEndList();
  195.     }
  196.     else {
  197.     glCallList(displayList);
  198.     free (sizeArray);
  199.     }
  200. }
  201.  
  202. void auxSolidBox (GLdouble width, GLdouble height, GLdouble depth)
  203. {
  204.     GLdouble *sizeArray, *tmp;
  205.     GLuint displayList;
  206.  
  207.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
  208.     tmp = sizeArray;
  209.     *tmp++ = width;
  210.     *tmp++ = height;
  211.     *tmp++ = depth;
  212.     displayList = findList (BOXSOLID, sizeArray, 3);
  213.  
  214.     if (displayList == 0) {
  215.     glNewList(makeModelPtr (BOXSOLID, sizeArray, 3),
  216.         GL_COMPILE_AND_EXECUTE);
  217.         drawbox(-width/2., width/2., -height/2., height/2., 
  218.         -depth/2., depth/2., GL_QUADS);
  219.     glEndList();
  220.     }
  221.     else {
  222.     glCallList(displayList);
  223.     free (sizeArray);
  224.     }
  225. }
  226.  
  227. /*  Render wire frame or solid tori.  If no display list with
  228.  *  the current model size exists, create a new display list.
  229.  */
  230. void auxWireTorus (GLdouble innerRadius, GLdouble outerRadius)
  231. {
  232.     GLdouble *sizeArray, *tmp;
  233.     GLuint displayList;
  234.  
  235.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  236.     tmp = sizeArray;
  237.     *tmp++ = innerRadius;
  238.     *tmp++ = outerRadius;
  239.     displayList = findList (TORUSWIRE, sizeArray, 2);
  240.  
  241.     if (displayList == 0) {
  242.     glNewList(makeModelPtr (TORUSWIRE, sizeArray, 2),
  243.         GL_COMPILE_AND_EXECUTE);
  244.         doughnut(innerRadius, outerRadius, 5, 10, GL_LINE_LOOP);
  245.     glEndList();
  246.     }
  247.     else {
  248.     glCallList(displayList);
  249.     free (sizeArray);
  250.     }
  251. }
  252.  
  253. void auxSolidTorus (GLdouble innerRadius, GLdouble outerRadius)
  254. {
  255.     GLdouble *sizeArray, *tmp;
  256.     GLuint displayList;
  257.  
  258.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  259.     tmp = sizeArray;
  260.     *tmp++ = innerRadius;
  261.     *tmp++ = outerRadius;
  262.     displayList = findList (TORUSSOLID, sizeArray, 2);
  263.  
  264.     if (displayList == 0) {
  265.     glNewList(makeModelPtr (TORUSSOLID, sizeArray, 2),
  266.         GL_COMPILE_AND_EXECUTE);
  267.         doughnut(innerRadius, outerRadius, 8, 15, GL_QUADS);
  268.     glEndList();
  269.     }
  270.     else {
  271.     glCallList(displayList);
  272.     free (sizeArray);
  273.     }
  274. }
  275.  
  276. /*  Render wire frame or solid cylinders.  If no display list with
  277.  *  the current model size exists, create a new display list.
  278.  */
  279. void auxWireCylinder (GLdouble radius, GLdouble height)
  280. {
  281.     GLUquadricObj *quadObj;
  282.     GLdouble *sizeArray, *tmp;
  283.     GLuint displayList;
  284.  
  285.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  286.     tmp = sizeArray;
  287.     *tmp++ = radius;
  288.     *tmp++ = height;
  289.     displayList = findList (CYLINDERWIRE, sizeArray, 2);
  290.  
  291.     if (displayList == 0) {
  292.     glNewList(makeModelPtr (CYLINDERWIRE, sizeArray, 2),
  293.         GL_COMPILE_AND_EXECUTE);
  294.         glPushMatrix ();
  295.         glRotatef (90.0, 1.0, 0.0, 0.0);
  296.         glTranslatef (0.0, 0.0, -1.0);
  297.         quadObj = gluNewQuadric ();
  298.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  299.         gluCylinder (quadObj, radius, radius, height, 12, 2);
  300.         glPopMatrix ();
  301.     glEndList();
  302.     }
  303.     else {
  304.     glCallList(displayList);
  305.     free (sizeArray);
  306.     }
  307. }
  308.  
  309. void auxSolidCylinder (GLdouble radius, GLdouble height)
  310. {
  311.     GLUquadricObj *quadObj;
  312.     GLdouble *sizeArray, *tmp;
  313.     GLuint displayList;
  314.  
  315.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  316.     tmp = sizeArray;
  317.     *tmp++ = radius;
  318.     *tmp++ = height;
  319.     displayList = findList (CYLINDERWIRE, sizeArray, 2);
  320.  
  321.     if (displayList == 0) {
  322.     glNewList(makeModelPtr (CYLINDERWIRE, sizeArray, 2),
  323.         GL_COMPILE_AND_EXECUTE);
  324.         glPushMatrix ();
  325.         glRotatef (90.0, 1.0, 0.0, 0.0);
  326.         glTranslatef (0.0, 0.0, -1.0);
  327.         quadObj = gluNewQuadric ();
  328.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  329.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  330.         gluCylinder (quadObj, radius, radius, height, 12, 2);
  331.         glPopMatrix ();
  332.     glEndList();
  333.     }
  334.     else {
  335.     glCallList(displayList);
  336.     free (sizeArray);
  337.     }
  338. }
  339.  
  340. /*  Render wire frame or solid icosahedra.  If no display list with
  341.  *  the current model size exists, create a new display list.
  342.  */
  343. void auxWireIcosahedron (GLdouble radius)
  344. {
  345.     GLdouble *sizeArray;
  346.     GLuint displayList;
  347.     GLdouble center[3] = {0.0, 0.0, 0.0};
  348.  
  349.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  350.     *sizeArray = radius;
  351.     displayList = findList (ICOSAWIRE, sizeArray, 1);
  352.  
  353.     if (displayList == 0) {
  354.     glNewList(makeModelPtr (ICOSAWIRE, sizeArray, 1),
  355.         GL_COMPILE_AND_EXECUTE);
  356.         icosahedron (center, radius, GL_LINE_LOOP);
  357.     glEndList();
  358.     }
  359.     else {
  360.     glCallList(displayList);
  361.     free (sizeArray);
  362.     }
  363. }
  364.  
  365. void auxSolidIcosahedron (GLdouble radius)
  366. {
  367.     GLdouble *sizeArray;
  368.     GLuint displayList;
  369.     GLdouble center[3] = {0.0, 0.0, 0.0};
  370.  
  371.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  372.     *sizeArray = radius;
  373.     displayList = findList (ICOSASOLID, sizeArray, 1);
  374.  
  375.     if (displayList == 0) {
  376.     glNewList(makeModelPtr (ICOSASOLID, sizeArray, 1),
  377.         GL_COMPILE_AND_EXECUTE);
  378.         icosahedron (center, radius, GL_TRIANGLES);
  379.     glEndList();
  380.     }
  381.     else {
  382.     glCallList(displayList);
  383.     free (sizeArray);
  384.     }
  385. }
  386.  
  387. /*  Render wire frame or solid octahedra.  If no display list with
  388.  *  the current model size exists, create a new display list.
  389.  */
  390. void auxWireOctahedron (GLdouble radius)
  391. {
  392.     GLdouble *sizeArray;
  393.     GLuint displayList;
  394.     GLdouble center[3] = {0.0, 0.0, 0.0};
  395.  
  396.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  397.     *sizeArray = radius;
  398.     displayList = findList (OCTAWIRE, sizeArray, 1);
  399.  
  400.     if (displayList == 0) {
  401.     glNewList(makeModelPtr (OCTAWIRE, sizeArray, 1),
  402.         GL_COMPILE_AND_EXECUTE);
  403.         octahedron (center, radius, GL_LINE_LOOP);
  404.     glEndList();
  405.     }
  406.     else {
  407.     glCallList(displayList);
  408.     free (sizeArray);
  409.     }
  410. }
  411.  
  412. void auxSolidOctahedron (GLdouble radius)
  413. {
  414.     GLdouble *sizeArray;
  415.     GLuint displayList;
  416.     GLdouble center[3] = {0.0, 0.0, 0.0};
  417.  
  418.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  419.     *sizeArray = radius;
  420.     displayList = findList (OCTASOLID, sizeArray, 1);
  421.  
  422.     if (displayList == 0) {
  423.     glNewList(makeModelPtr (OCTASOLID, sizeArray, 1),
  424.         GL_COMPILE_AND_EXECUTE);
  425.         octahedron (center, radius, GL_TRIANGLES);
  426.     glEndList();
  427.     }
  428.     else {
  429.     glCallList(displayList);
  430.     free (sizeArray);
  431.     }
  432. }
  433.  
  434. /*  Render wire frame or solid tetrahedra.  If no display list with
  435.  *  the current model size exists, create a new display list.
  436.  */
  437. void auxWireTetrahedron (GLdouble radius)
  438. {
  439.     GLdouble *sizeArray;
  440.     GLuint displayList;
  441.     GLdouble center[3] = {0.0, 0.0, 0.0};
  442.  
  443.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  444.     *sizeArray = radius;
  445.     displayList = findList (TETRAWIRE, sizeArray, 1);
  446.  
  447.     if (displayList == 0) {
  448.     glNewList(makeModelPtr (TETRAWIRE, sizeArray, 1),
  449.         GL_COMPILE_AND_EXECUTE);
  450.         tetrahedron (center, radius, GL_LINE_LOOP);
  451.     glEndList();
  452.     }
  453.     else {
  454.     glCallList(displayList);
  455.     free (sizeArray);
  456.     }
  457. }
  458.  
  459. void auxSolidTetrahedron (GLdouble radius)
  460. {
  461.     GLdouble *sizeArray;
  462.     GLuint displayList;
  463.     GLdouble center[3] = {0.0, 0.0, 0.0};
  464.  
  465.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  466.     *sizeArray = radius;
  467.     displayList = findList (TETRASOLID, sizeArray, 1);
  468.  
  469.     if (displayList == 0) {
  470.     glNewList(makeModelPtr (TETRASOLID, sizeArray, 1),
  471.         GL_COMPILE_AND_EXECUTE);
  472.         tetrahedron (center, radius, GL_TRIANGLES);
  473.     glEndList();
  474.     }
  475.     else {
  476.     glCallList(displayList);
  477.     free (sizeArray);
  478.     }
  479. }
  480.  
  481. /*  Render wire frame or solid dodecahedra.  If no display list with
  482.  *  the current model size exists, create a new display list.
  483.  */
  484. void auxWireDodecahedron (GLdouble radius)
  485. {
  486.     GLdouble *sizeArray;
  487.     GLuint displayList;
  488.     GLdouble center[3] = {0.0, 0.0, 0.0};
  489.  
  490.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  491.     *sizeArray = radius;
  492.     displayList = findList (DODECAWIRE, sizeArray, 1);
  493.  
  494.     if (displayList == 0) {
  495.     glNewList(makeModelPtr (DODECAWIRE, sizeArray, 1),
  496.         GL_COMPILE_AND_EXECUTE);
  497.         dodecahedron (center, radius/1.73, GL_LINE_LOOP);
  498.     glEndList();
  499.     }
  500.     else {
  501.     glCallList(displayList);
  502.     free (sizeArray);
  503.     }
  504. }
  505.  
  506. void auxSolidDodecahedron (GLdouble radius)
  507. {
  508.     GLdouble *sizeArray;
  509.     GLuint displayList;
  510.     GLdouble center[3] = {0.0, 0.0, 0.0};
  511.  
  512.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  513.     *sizeArray = radius;
  514.     displayList = findList (DODECASOLID, sizeArray, 1);
  515.  
  516.     if (displayList == 0) {
  517.     glNewList(makeModelPtr (DODECASOLID, sizeArray, 1),
  518.         GL_COMPILE_AND_EXECUTE);
  519.         dodecahedron (center, radius/1.73, GL_TRIANGLE_FAN);
  520.     glEndList();
  521.     }
  522.     else {
  523.     glCallList(displayList);
  524.     free (sizeArray);
  525.     }
  526. }
  527.  
  528. /*  Render wire frame or solid cones.  If no display list with
  529.  *  the current model size exists, create a new display list.
  530.  */
  531. void auxWireCone (GLdouble base, GLdouble height)
  532. {
  533.     GLUquadricObj *quadObj;
  534.     GLdouble *sizeArray, *tmp;
  535.     GLuint displayList;
  536.  
  537.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  538.     tmp = sizeArray;
  539.     *tmp++ = base;
  540.     *tmp++ = height;
  541.     displayList = findList (CONEWIRE, sizeArray, 2);
  542.  
  543.     if (displayList == 0) {
  544.     glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
  545.         GL_COMPILE_AND_EXECUTE);
  546.         quadObj = gluNewQuadric ();
  547.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  548.         gluCylinder (quadObj, base, 0.0, height, 15, 10);
  549.     glEndList();
  550.     }
  551.     else {
  552.     glCallList(displayList);
  553.     free (sizeArray);
  554.     }
  555. }
  556.  
  557. void auxSolidCone (GLdouble base, GLdouble height)
  558. {
  559.     GLUquadricObj *quadObj;
  560.     GLdouble *sizeArray, *tmp;
  561.     GLuint displayList;
  562.  
  563.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  564.     tmp = sizeArray;
  565.     *tmp++ = base;
  566.     *tmp++ = height;
  567.     displayList = findList (CONEWIRE, sizeArray, 2);
  568.  
  569.     if (displayList == 0) {
  570.     glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
  571.         GL_COMPILE_AND_EXECUTE);
  572.         quadObj = gluNewQuadric ();
  573.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  574.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  575.         gluCylinder (quadObj, base, 0.0, height, 15, 10);
  576.     glEndList();
  577.     }
  578.     else {
  579.     glCallList(displayList);
  580.     free (sizeArray);
  581.     }
  582. }
  583.  
  584. /* Routines to build 3 dimensional solids, including:
  585.  *
  586.  * drawbox, doughnut, icosahedron, 
  587.  * octahedron, tetrahedron, dodecahedron.
  588.  */
  589.  
  590. /* drawbox:
  591.  *
  592.  * draws a rectangular box with the given x, y, and z ranges.  
  593.  * The box is axis-aligned.
  594.  */
  595. void drawbox(GLdouble x0, GLdouble x1, GLdouble y0, GLdouble y1,
  596.     GLdouble z0, GLdouble z1, GLenum type)
  597. {
  598.     static GLdouble n[6][3] = {
  599.     {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
  600.     {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}
  601.     };
  602.     static GLint faces[6][4] = {
  603.     { 0, 1, 2, 3 }, { 3, 2, 6, 7 }, { 7, 6, 5, 4 },
  604.     { 4, 5, 1, 0 }, { 5, 6, 2, 1 }, { 7, 4, 0, 3 }
  605.     };
  606.     GLdouble v[8][3], tmp;
  607.     GLint i;
  608.  
  609.     if (x0 > x1) {
  610.     tmp = x0; x0 = x1; x1 = tmp;
  611.     }
  612.     if (y0 > y1) {
  613.     tmp = y0; y0 = y1; y1 = tmp; 
  614.     }
  615.     if (z0 > z1) {
  616.     tmp = z0; z0 = z1; z1 = tmp; 
  617.     }
  618.     v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
  619.     v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
  620.     v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
  621.     v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
  622.     v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
  623.     v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
  624.  
  625.     for (i = 0; i < 6; i++) {
  626.     glBegin(type);
  627.     glNormal3dv(&n[i][0]);
  628.     glVertex3dv(&v[faces[i][0]][0]);
  629.     glNormal3dv(&n[i][0]);
  630.     glVertex3dv(&v[faces[i][1]][0]);
  631.     glNormal3dv(&n[i][0]);
  632.     glVertex3dv(&v[faces[i][2]][0]);
  633.     glNormal3dv(&n[i][0]);
  634.     glVertex3dv(&v[faces[i][3]][0]);
  635.     glEnd();
  636.     }
  637. }
  638.  
  639. /* doughnut:
  640.  *
  641.  * draws a doughnut, centered at (0, 0, 0) whose axis is aligned with
  642.  * the z-axis.  The doughnut's major radius is R, and minor radius is r.
  643.  */
  644.  
  645. void doughnut(GLdouble r, GLdouble R, GLint nsides, GLint rings, GLenum type)
  646. {
  647.     int    i, j;
  648.     GLdouble    theta, phi, theta1, phi1;
  649.     GLdouble    p0[03], p1[3], p2[3], p3[3];
  650.     GLdouble    n0[3], n1[3], n2[3], n3[3];
  651.  
  652.     for (i = 0; i < rings; i++) {
  653.     theta = (GLdouble)i*2.0*PI/rings;
  654.     theta1 = (GLdouble)(i+1)*2.0*PI/rings;
  655.     for (j = 0; j < nsides; j++) {
  656.         phi = (GLdouble)j*2.0*PI/nsides;
  657.         phi1 = (GLdouble)(j+1)*2.0*PI/nsides;
  658.  
  659.         p0[0] = cos(theta)*(R + r*cos(phi));
  660.         p0[1] = -sin(theta)*(R + r*cos(phi));
  661.         p0[2] = r*sin(phi);
  662.  
  663.         p1[0] = cos(theta1)*(R + r*cos(phi));
  664.         p1[1] = -sin(theta1)*(R + r*cos(phi));
  665.         p1[2] = r*sin(phi);
  666.  
  667.         p2[0] = cos(theta1)*(R + r*cos(phi1));
  668.         p2[1] = -sin(theta1)*(R + r*cos(phi1));
  669.         p2[2] = r*sin(phi1);
  670.  
  671.         p3[0] = cos(theta)*(R + r*cos(phi1));
  672.         p3[1] = -sin(theta)*(R + r*cos(phi1));
  673.         p3[2] = r*sin(phi1);
  674.  
  675.         n0[0] = cos(theta)*(cos(phi));
  676.         n0[1] = -sin(theta)*(cos(phi));
  677.         n0[2] = sin(phi);
  678.  
  679.         n1[0] = cos(theta1)*(cos(phi));
  680.         n1[1] = -sin(theta1)*(cos(phi));
  681.         n1[2] = sin(phi);
  682.  
  683.         n2[0] = cos(theta1)*(cos(phi1));
  684.         n2[1] = -sin(theta1)*(cos(phi1));
  685.         n2[2] = sin(phi1);
  686.  
  687.         n3[0] = cos(theta)*(cos(phi1));
  688.         n3[1] = -sin(theta)*(cos(phi1));
  689.         n3[2] = sin(phi1);
  690.  
  691.         m_xformpt(p0, p0, n0, n0);
  692.         m_xformpt(p1, p1, n1, n1);
  693.         m_xformpt(p2, p2, n2, n2);
  694.         m_xformpt(p3, p3, n3, n3);
  695.  
  696.         glBegin(type);
  697.         glNormal3dv(n3);
  698.         glVertex3dv(p3);
  699.         glNormal3dv(n2);
  700.         glVertex3dv(p2);
  701.         glNormal3dv(n1);
  702.         glVertex3dv(p1);
  703.         glNormal3dv(n0);
  704.         glVertex3dv(p0);
  705.         glEnd();
  706.     }
  707.     }
  708. }
  709.  
  710. /* octahedron data: The octahedron produced is centered 
  711.  * at the origin and has radius 1.0 
  712.  */
  713. static GLdouble odata[6][3] = {
  714.   {1.0, 0.0, 0.0},
  715.   {-1.0, 0.0, 0.0},
  716.   {0.0, 1.0, 0.0},
  717.   {0.0, -1.0, 0.0},
  718.   {0.0, 0.0, 1.0},
  719.   {0.0, 0.0, -1.0}
  720. };
  721.  
  722. static int ondex[8][3] = {
  723.     {0, 4, 2}, {1, 2, 4}, {0, 3, 4}, {1, 4, 3},
  724.     {0, 2, 5}, {1, 5, 2}, {0, 5, 3}, {1, 3, 5}
  725. };
  726.  
  727. /* tetrahedron data: */
  728.  
  729. #define T    1.73205080756887729
  730.  
  731. static GLdouble tdata[4][3] = {
  732.     {T, T, T}, {T, -T, -T}, {-T, T, -T}, {-T, -T, T}
  733. };
  734.  
  735. static int tndex[4][3] = {
  736.     {0, 1, 3}, {2, 1, 0}, {3, 2, 0}, {1, 2, 3}
  737. };
  738.  
  739. /* icosahedron data: These numbers are rigged to 
  740.  * make an icosahedron of radius 1.0 
  741.  */
  742.  
  743. #define X .525731112119133606
  744. #define Z .850650808352039932
  745.  
  746. static GLdouble idata[12][3] = {
  747.   {-X, 0, Z},
  748.   {X, 0, Z},
  749.   {-X, 0, -Z},
  750.   {X, 0, -Z},
  751.   {0, Z, X},
  752.   {0, Z, -X},
  753.   {0, -Z, X},
  754.   {0, -Z, -X},
  755.   {Z, X, 0},
  756.   {-Z, X, 0},
  757.   {Z, -X, 0},
  758.   {-Z, -X, 0}
  759. };
  760.  
  761. static int index[20][3] = {
  762.     {0, 4, 1},    {0, 9, 4},
  763.     {9, 5, 4},    {4, 5, 8},
  764.     {4, 8, 1},    {8, 10, 1},
  765.     {8, 3, 10},    {5, 3, 8},
  766.     {5, 2, 3},    {2, 7, 3},
  767.     {7, 10, 3},    {7, 6, 10},
  768.     {7, 11, 6},    {11, 0, 6},
  769.     {0, 1, 6},    {6, 1, 10},
  770.     {9, 0, 11},    {9, 11, 2},
  771.     {9, 2, 5},    {7, 2, 11},
  772. };
  773.  
  774. /* icosahedron:
  775.  *
  776.  * Draws an icosahedron with center at p0 having the
  777.  * given radius.
  778.  */
  779.  
  780. static void icosahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  781. {
  782.     int i;
  783.  
  784.     for (i = 0; i < 20; i++)
  785.     drawtriangle(i, 0, 1, p0, radius, shadeType, 0);
  786. }
  787.  
  788. /* octahedron:
  789.  *
  790.  * Draws an octahedron with center at p0 having the
  791.  * given radius.
  792.  */
  793. static void octahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  794. {
  795.     int i;
  796.  
  797.     for (i = 0; i < 8; i++)
  798.     drawtriangle(i, 1, 1, p0, radius, shadeType, 0);
  799. }
  800.  
  801. /* tetrahedron:
  802.  *
  803.  * Draws an tetrahedron with center at p0 having the
  804.  * given radius.
  805.  */
  806.  
  807. static void tetrahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  808. {
  809.     int i;
  810.  
  811.     for (i = 0; i < 4; i++)
  812.     drawtriangle(i, 2, 1, p0, radius, shadeType, 0);
  813. }
  814.  
  815. static void subdivide(int depth, GLdouble *v0, GLdouble *v1, GLdouble *v2,
  816.     GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
  817. {
  818.     GLdouble w0[3], w1[3], w2[3];
  819.     GLdouble l;
  820.     int i, j, k, n;
  821.  
  822.     for (i = 0; i < depth; i++)
  823.     for (j = 0; i + j < depth; j++) {
  824.         k = depth - i - j;
  825.         for (n = 0; n < 3; n++) {
  826.         w0[n] = (i*v0[n] + j*v1[n] + k*v2[n])/depth;
  827.         w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
  828.         w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
  829.         }
  830.         l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
  831.         w0[0] /= l; w0[1] /= l; w0[2] /= l;
  832.         l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
  833.         w1[0] /= l; w1[1] /= l; w1[2] /= l;
  834.         l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
  835.         w2[0] /= l; w2[1] /= l; w2[2] /= l;
  836.         recorditem(w1, w0, w2, p0, radius, shadeType, avnormal);
  837.     }
  838.     for (i = 0; i < depth-1; i++)
  839.     for (j = 0; i + j < depth-1; j++) {
  840.         k = depth - i - j;
  841.         for (n = 0; n < 3; n++) {
  842.         w0[n] = ((i+1)*v0[n] + (j+1)*v1[n] + (k-2)*v2[n])/depth;
  843.         w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
  844.         w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
  845.         }
  846.         l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
  847.         w0[0] /= l; w0[1] /= l; w0[2] /= l;
  848.         l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
  849.         w1[0] /= l; w1[1] /= l; w1[2] /= l;
  850.         l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
  851.         w2[0] /= l; w2[1] /= l; w2[2] /= l;
  852.         recorditem(w0, w1, w2, p0, radius, shadeType, avnormal);
  853.     }
  854. }
  855.  
  856. static void drawtriangle(int i, int geomType, int depth,
  857.     GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
  858. {
  859.     GLdouble *x0, *x1, *x2;
  860.  
  861.     switch (geomType) {
  862.     case 0:    /* icosahedron */
  863.         x0 = &idata[index[i][0]][0];
  864.         x1 = &idata[index[i][1]][0];
  865.         x2 = &idata[index[i][2]][0];
  866.         break;
  867.     case 1: /* octahedron */
  868.         x0 = &odata[ondex[i][0]][0];
  869.         x1 = &odata[ondex[i][1]][0];
  870.         x2 = &odata[ondex[i][2]][0];
  871.         break;
  872.     case 2: /* tetrahedron */
  873.         x0 = &tdata[tndex[i][0]][0];
  874.         x1 = &tdata[tndex[i][1]][0];
  875.         x2 = &tdata[tndex[i][2]][0];
  876.         break;
  877.     }
  878.     subdivide(depth, x0, x1, x2, p0, radius, shadeType, avnormal);
  879. }
  880.  
  881. static void recorditem(GLdouble *n1, GLdouble *n2, GLdouble *n3,
  882.     GLdouble center[3], GLdouble radius, GLenum shadeType, int avnormal)
  883. {
  884.     GLdouble p1[3], p2[3], p3[3], q0[3], q1[3], n11[3], n22[3], n33[3];
  885.     int    i;
  886.  
  887.     for (i = 0; i < 3; i++) {
  888.     p1[i] = n1[i]*radius + center[i];
  889.     p2[i] = n2[i]*radius + center[i];
  890.     p3[i] = n3[i]*radius + center[i];
  891.     }
  892.     if (avnormal == 0) {
  893.     diff3(p1, p2, q0);
  894.     diff3(p2, p3, q1);
  895.     crossprod(q0, q1, q1);
  896.     normalize(q1);
  897.     m_xformpt(p1, p1, q1, n11);
  898.     m_xformptonly(p2, p2);
  899.     m_xformptonly(p3, p3);
  900.  
  901.     glBegin (shadeType);
  902.     glNormal3dv(n11);
  903.     glVertex3dv(p1);
  904.     glVertex3dv(p2);
  905.     glVertex3dv(p3);
  906.     glEnd();
  907.     return;
  908.     }
  909.     m_xformpt(p1, p1, n1, n11);
  910.     m_xformpt(p2, p2, n2, n22);
  911.     m_xformpt(p3, p3, n3, n33);
  912.  
  913.     glBegin (shadeType);
  914.     glNormal3dv(n11);
  915.     glVertex3dv(p1);
  916.     glNormal3dv(n22);
  917.     glVertex3dv(p2);
  918.     glNormal3dv(n33);
  919.     glVertex3dv(p3);
  920.     glEnd();
  921. }
  922.  
  923. static GLdouble dodec[20][3];
  924.  
  925. static void initdodec()
  926. {
  927.     GLdouble alpha, beta;
  928.  
  929.     alpha = sqrt(2.0/(3.0 + sqrt(5.0)));
  930.     beta = 1.0 + sqrt(6.0/(3.0 + sqrt(5.0)) - 2.0 + 2.0*sqrt(2.0/(3.0 +
  931.                                 sqrt(5.0))));
  932.     dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
  933.     dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
  934.     dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
  935.     dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
  936.     dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
  937.     dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
  938.     dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
  939.     dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
  940.     dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
  941.     dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
  942.     dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
  943.     dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
  944.     dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
  945.     dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
  946.     dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
  947.     dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
  948.     dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
  949.     dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
  950.     dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
  951.     dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
  952. }
  953.  
  954. /* dodecahedron:
  955.  *
  956.  * Draws an dodecahedron with center at 0.0. The radius
  957.  * is sqrt(3).
  958.  */
  959. static void dodecahedron(GLdouble center[3], GLdouble sc, GLenum type)
  960. {
  961.     static int inited = 0;
  962.  
  963.     if ( inited == 0) {
  964.     inited = 1;
  965.     initdodec();
  966.     }
  967.     m_pushmatrix();
  968.     m_translate(center[0], center[1], center[2]);
  969.     m_scale(sc, sc, sc);
  970.     pentagon(0, 1, 9, 16, 5, type);
  971.     pentagon(1, 0, 3, 18, 7, type);
  972.     pentagon(1, 7, 11, 10, 9, type);
  973.     pentagon(11, 7, 18, 19, 6, type);
  974.     pentagon(8, 17, 16, 9, 10, type);
  975.     pentagon(2, 14, 15, 6, 19, type);
  976.     pentagon(2, 13, 12, 4, 14, type);
  977.     pentagon(2, 19, 18, 3, 13, type);
  978.     pentagon(3, 0, 5, 12, 13, type);
  979.     pentagon(6, 15, 8, 10, 11, type);
  980.     pentagon(4, 17, 8, 15, 14, type);
  981.     pentagon(4, 12, 5, 16, 17, type);
  982.     m_popmatrix();
  983. }
  984.  
  985. static void pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
  986. {
  987.     GLdouble n0[3], d1[3], d2[3], d3[3], d4[3], d5[3], nout[3];
  988.  
  989.     diff3(&dodec[a][0], &dodec[b][0], d1);
  990.     diff3(&dodec[b][0], &dodec[c][0], d2);
  991.     crossprod(d1, d2, n0);
  992.     normalize(n0);
  993.     m_xformpt(&dodec[a][0], d1, n0, nout);
  994.     m_xformptonly(&dodec[b][0], d2);
  995.     m_xformptonly(&dodec[c][0], d3);
  996.     m_xformptonly(&dodec[d][0], d4);
  997.     m_xformptonly(&dodec[e][0], d5);
  998.  
  999.     glBegin (shadeType);
  1000.     glNormal3dv(nout);
  1001.     glVertex3dv(d1);
  1002.     glVertex3dv(d2);
  1003.     glVertex3dv(d3);
  1004.     glVertex3dv(d4);
  1005.     glVertex3dv(d5);
  1006.     glEnd();
  1007. }
  1008.  
  1009. /*    linked lists--display lists for each different 
  1010.  *    type of geometric objects.  The linked list is 
  1011.  *    searched, until an object of the requested
  1012.  *    size is found.  If no geometric object of that size
  1013.  *    has been previously made, a new one is created.
  1014.  */
  1015. GLuint findList (int index, GLdouble *paramArray, int size) 
  1016. {
  1017.     MODELPTR endList;
  1018.     int found = 0;
  1019.     
  1020.     endList = lists[index];
  1021.     while (endList != NULL) {
  1022.     if (compareParams (endList->params, paramArray, size))
  1023.         return (endList->list);
  1024.     endList = endList->ptr;
  1025.     }
  1026. /*  if not found, return 0 and calling routine should
  1027.  *  make a new list    
  1028.  */
  1029.     return (0);
  1030. }
  1031.  
  1032. int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size) 
  1033. {
  1034.     int i;
  1035.     int matches = 1;
  1036.  
  1037.     for (i = 0; (i < size) && matches; i++) {
  1038.     if (*oneArray++ != *twoArray++)
  1039.         matches = 0;
  1040.     }
  1041.     return (matches);
  1042. }
  1043.  
  1044. GLuint makeModelPtr (int index, GLdouble *sizeArray, int count)
  1045. {
  1046.     MODELPTR newModel;
  1047.  
  1048.     newModel = (MODELPTR) malloc (sizeof (MODEL));
  1049.     newModel->list = glGenLists (1);
  1050.     newModel->numParam = count;
  1051.     newModel->params = sizeArray;
  1052.     newModel->ptr = lists[index];
  1053.     lists[index] = newModel;
  1054.  
  1055.     return (newModel->list);
  1056. }
  1057.